package com.twq.types.typeparam.mean

/**
 * Created by tangweiqun on 2017/12/6.
 * 1、elems是类Queue的构造参数，我们也称之为值参数
 * 2、如果只有值参数的话，那么Queue只能装Int类型的值，装不了其他类型的值，但是这个时候Queue是一个类型
 * 3、如果我们的Queue想装其他类型的值，我们可以给Queue定义类型参数
 * 4、类型参数在类定义的后面用[]来定义
 * 5、给Queue定义了一个类型参数T，使得Queue可以装任何类型的值参数，但是这个时候Queue不是一个类型，是因为它需要接受一个类型参数
 */

class Queue[T](elems: List[T]) {

  def head: T = elems.head

  def tail: Queue[T] = new Queue(elems.tail)

  override def toString: String = elems.mkString(",")

}


object Queue {
  def main(args: Array[String]): Unit = {
    val q1 = new Queue(List(1, 3, 1))
    q1.tail

    //val q2 = new Queue(List("this", "is", "a", "example"))
    //q2.tail


    //编译报错，因为Queue不是一个类型
    //def doesNotCompile(q: Queue) = {}

    //需要为Queue指定一个参数化的类型，比如Queue[AnyRef]
    //Queue是一个class，但不是type(类型)
    //def doseCompile(q: Queue[AnyRef]) = {}

    //我们可以将Queue称之为type constructor(类型构造器)，
    // 因为Queue需要接受一个类型参数才能构造出一个类型，这个和new一个类，然后接受值参数，然后构造出对象一样
    // 比如Queue[Int], Queue[String]等

    //我们也可以称Queue为generic class(泛型类)
    //Queue是一个通用的Queue，然后带上类型参数后就是特殊的Queue类型了

    //Queue我们还可以称之为High-kinded type(高阶类型)
    // 利用其他的类型来构造一个类型

    //trait也可以接受类型参数，比如:
    trait Cell[T] {
      override def toString: String = "cell"
    }

    //函数也是可以接受类型参数的，比如：
    def test[T](list: List[T]) = list.mkString

    test(List(1, 2, 3))
  }
}
